using System;
using System.Linq;
using System.Collections.Generic;
using System.Web.UI;
using System.ComponentModel;
using System.Xml;
using ASPNETVN.PORTAL.Modules.ACTP.Components;

namespace ASPNETVN.PORTAL.Modules.ACTP.Controls
{
    [DefaultProperty("XmlData"), ToolboxData("<{0}:GanttChartControl runat=server></{0}:GanttChartControl>")]
    public class ProjectGanttChartControl : System.Web.UI.WebControls.WebControl
    {
        private string _CellWidth, _CellHeight;
        string[] _Names;

        public ProjectGanttChartControl()
        {
            _Names = new string[3];
        }

        #region Public Properties

        /// <summary>
        /// Gets or sets a value that contains XML data containing the events.
        /// </summary>
        [Bindable(true), Category("Appearance"), DefaultValue("")]
        public string XmlData { get; set; }

        [Bindable(true), Category("Appearance"), DefaultValue(0)]
        public int ProjectID { get; set; }

        /// <summary>
        /// Gets or sets a value that indicates the quarter (1,2,3,4)
        /// </summary>
        [Bindable(true), Category("Appearance"), DefaultValue(1)]
        public int Quarter { get; set; }

        /// <summary>
        /// Gets or sets a value that indicates the Year e.g. 2005
        /// </summary>
        [Bindable(true), Category("Appearance"), DefaultValue("")]
        public int Year { get; set; }

        /// <summary>
        /// Gets or sets a value that indicates the default BlockColor
        /// </summary>
        [Bindable(true), Category("Appearance"), DefaultValue("red")]
        public string BlockColor { get; set; }

        /// <summary>
        /// Gets or sets a value that indicates the cell width of the event calendar 'grid'
        /// </summary>
        [Bindable(true), Category("Appearance"), DefaultValue("15")]
        public int CellWidth
        {
            get
            {
                return int.Parse(_CellWidth);
            }

            set
            {
                _CellWidth = value.ToString();
            }
        }

        /// <summary>
        /// Gets or sets a value that indicates the cell height of the event calendar 'grid'
        /// </summary>
        [Bindable(true), Category("Appearance"), DefaultValue("18")]
        public int CellHeight
        {
            get
            {
                return int.Parse(_CellHeight);
            }

            set
            {
                _CellHeight = value.ToString();
            }
        }

        /// <summary>
        /// Gets or sets a value that indicates a color the event calendar will use to delimit the day names and event names.
        /// </summary>		
        [Bindable(true), Category("Appearance"), DefaultValue("#dcdcdc")]
        public string ToggleColor { get; set; }

        /// <summary>
        /// Gets or sets a value that indicates a color the event calendar will use to delimit the day names and event names.
        /// </summary>		
        [Bindable(true), Category("Appearance"), DefaultValue("#dcdcdc")]
        public string BlankGifPath { get; set; }

        #endregion

        #region Event Handling

        /// <summary>
        /// writes out some javascript so the calendar grid can resize itself
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            if (!base.Page.IsStartupScriptRegistered("EventCalendar"))
            {
                base.Page.RegisterStartupScript("EventCalendar",
                    "<script>" +
                    "function ResizeTables()" +
                    "{" +
                    "document.getElementById('divcal').style.width = '1px';" +
                    "document.getElementById('divcal').style.width = document.getElementById('tblcal').clientWidth + 'px';" +
                    "};" +
                    "</script>");

                base.Page.RegisterStartupScript("EventCalendarOnLoad",
                    "<SCRIPT FOR=window EVENT=onload>" +
                    "ResizeTables();" +
                    "</script>");

                base.Page.RegisterStartupScript("EventCalendarOnResize",
                    "<SCRIPT FOR=window EVENT=onresize>" +
                    "ResizeTables();" +
                    "</script>");
            }
        }

        protected override void Render(HtmlTextWriter writer)
        {
            // create a 2 column, 1 row table, the first column will contain the text for the tasks that
            // is non scrollable.

            writer.AddAttribute("border", "0");
            writer.AddAttribute("cellSpacing", "0");
            writer.AddAttribute("cellPadding", "0");
            writer.AddAttribute("width", "100%");
            writer.RenderBeginTag("table");
            writer.RenderBeginTag("tr");


            writer.AddAttribute("valign", "top");
            writer.AddAttribute("align", "right");
            writer.RenderBeginTag("td nowrap");

            RenderLeftHandPane(writer);

            writer.RenderEndTag();

            writer.AddAttribute("id", "tblcal");
            writer.AddAttribute("valign", "top");
            writer.AddAttribute("align", "left");
            writer.AddAttribute("width", "100%");
            writer.RenderBeginTag("td nowrap");

            RenderRightHandPane(writer);

            writer.RenderEndTag();
            writer.RenderEndTag();
            writer.RenderEndTag();


        }
        #endregion

        #region Helper Functions

        //private void RenderTooltip(HtmlTextWriter writer)
        //{
        //    Project project = Project.Load(this.ProjectID);
        //    IList<Task> tasks = Task.SelectCollectionBy_ProjectID(project.ModuleID, project.ProjectID);
        //    foreach (Task task in tasks)
        //    {
                
        //    }
        //}

        private void RenderLeftHandPane(HtmlTextWriter writer)
        {

            string blocktext, grouptext;

            writer.AddAttribute("border", "1");
            writer.AddAttribute("style", "border-collapse: collapse;");
            writer.AddAttribute("cellspacing", "0");
            writer.AddAttribute("cellpadding", "4");
            writer.AddAttribute("class", "Grid");
            writer.RenderBeginTag("table");

            //empty row to match month headers on right hand pane
            writer.AddAttribute("class", "GridHeader");
            writer.RenderBeginTag("tr");
            writer.RenderBeginTag("th");
            // Month
            writer.Write("");
            writer.RenderEndTag();
            writer.RenderEndTag();

            //empty row to match day headers on right hand pane
            writer.AddAttribute("class", "GridHeader");
            writer.RenderBeginTag("tr");
            writer.RenderBeginTag("th");
            // Weekday
            writer.Write("");
            writer.RenderEndTag();
            writer.RenderEndTag();


            Project project = Project.Load(this.ProjectID);
            IList<Task> tasks = Task.SelectCollectionBy_ProjectID(project.ModuleID, project.ProjectID);
            IList<TaskMilestone> taskMilestones = TaskMilestone.SelectCollectionBy_ProjectID(this.ProjectID);
            IList<ProjectTask> projectTasks = ProjectTask.SelectCollectionBy_ProjectID(this.ProjectID);


            foreach (TaskMilestone taskMilestone in taskMilestones)
            {
                grouptext = taskMilestone.Title;

                writer.AddAttribute("class", "GridHeader");
                writer.RenderBeginTag("tr");
                writer.RenderBeginTag("th");
                //writer.Write("&nbsp;" + grouptext + "&nbsp;<img src='" + BlankGifPath + "' height=" + _CellHeight + " width='1px' />");
                writer.Write(grouptext);
                writer.RenderEndTag();
                writer.RenderEndTag();

                foreach (ProjectTask projectTask in projectTasks)
                {
                    if (projectTask.TaskMilestoneID == taskMilestone.TaskMilestoneID)
                    {
                        ProjectTask pt = projectTask;
                        Task task = tasks.FirstOrDefault(x => x.TaskID == pt.TaskID);
                        if (task != null)
                        {
                            writer.RenderBeginTag("tr");

                            blocktext = task.Subject;

                            //write the activity
                            //writer.AddAttribute("height", _CellHeight);
                            writer.RenderBeginTag("td nowrap");
                            //writer.Write("&nbsp;" + blocktext + "&nbsp;<img src='" + BlankGifPath + "' height=" + _CellHeight + " width='1px' />");
                            writer.Write(blocktext);
                            writer.RenderEndTag();

                            writer.RenderEndTag();
                        }
                    }
                }
            }
            writer.RenderEndTag();


            //// now need to write the rows
            //// Load the XML
            //XmlDocument xmlDoc = new XmlDocument();
            //xmlDoc.LoadXml(XmlData);

            //XmlNodeList xmlRows = xmlDoc.SelectNodes("//group");
            //foreach (XmlNode xmlRow in xmlRows)
            //{
            //    grouptext = xmlRow.SelectSingleNode("name").InnerText;
            //    writer.AddAttribute("class", "GridHeader");
            //    writer.RenderBeginTag("tr");
            //    writer.RenderBeginTag("th");
            //    //writer.Write("&nbsp;" + grouptext + "&nbsp;<img src='" + BlankGifPath + "' height=" + _CellHeight + " width='1px' />");
            //    writer.Write(grouptext);
            //    writer.RenderEndTag();
            //    writer.RenderEndTag();

            //    XmlNodeList xmlBlocks = xmlRow.SelectNodes("block");
            //    foreach (XmlNode xmlBlock in xmlBlocks)
            //    {
            //        writer.RenderBeginTag("tr");

            //        blocktext = xmlBlock.SelectSingleNode("name").InnerText;

            //        //write the activity
            //        //writer.AddAttribute("height", _CellHeight);
            //        writer.RenderBeginTag("td nowrap");
            //        //writer.Write("&nbsp;" + blocktext + "&nbsp;<img src='" + BlankGifPath + "' height=" + _CellHeight + " width='1px' />");
            //        writer.Write(blocktext);
            //        writer.RenderEndTag();

            //        writer.RenderEndTag();
            //    }
            //}
            //writer.RenderEndTag();
        }

        private void RenderRightHandPane(HtmlTextWriter writer)
        {
            string startdate, enddate, dayname, href, blocktext, blockcolor;
            int startindex, endindex, imagewidth, month;
            bool week = false;
            QuarterHelper quarter = new QuarterHelper(Year, Quarter);

            writer.AddAttribute("style", "width:1px; overflow-x:scroll;");
            writer.AddAttribute("id", "divcal");
            writer.RenderBeginTag("div");

            writer.AddAttribute("border", "1");
            writer.AddAttribute("style", "border-collapse: collapse;");
            writer.AddAttribute("cellSpacing", "0");
            writer.AddAttribute("cellPadding", "4");
            writer.AddAttribute("class", "Grid");
            writer.RenderBeginTag("table");

            //write month headers
            writer.AddAttribute("class", "GridHeader");
            writer.RenderBeginTag("tr");
            for (int i = 1; i <= 3; i++)
            {
                month = i + (3 * (quarter.QuarterIndex - 1));
                writer.AddAttribute("colspan", quarter.TotalDaysInMonth(month).ToString());
                writer.RenderBeginTag("th");
                writer.Write(quarter.GetMonthName(i));
                writer.RenderEndTag();
            };
            writer.RenderEndTag();

            //write day headers
            writer.AddAttribute("class", "GridHeader");
            writer.RenderBeginTag("tr");
            for (int i = (3 * quarter.QuarterIndex - 2); i <= (3 * quarter.QuarterIndex); i++)
            {
                for (int j = 1; j <= quarter.TotalDaysInMonth(i); j++)
                {
                    dayname = quarter.GetDayName(i, j);
                    if (dayname == "M") week = !week;

                    writer.AddAttribute("align", "center");
                    writer.AddAttribute("style", "padding-left:6px!important;padding-right:6px!important");
                   
                    if (week) writer.AddAttribute("bgcolor", ToggleColor);
                    writer.RenderBeginTag("th");
                    writer.Write(dayname);
                    writer.RenderEndTag();
                }
            }
            writer.RenderEndTag();

            // now need to write the rows
            // Load the XML
            //XmlDocument xmlDoc = new XmlDocument();
            //xmlDoc.LoadXml(XmlData);

            Project project = Project.Load(this.ProjectID);
            IList<Task> tasks = Task.SelectCollectionBy_ProjectID(project.ModuleID, project.ProjectID);
            IList<TaskMilestone> taskMilestones = TaskMilestone.SelectCollectionBy_ProjectID(this.ProjectID);
            IList<ProjectTask> projectTasks = ProjectTask.SelectCollectionBy_ProjectID(this.ProjectID);

            //XmlNodeList xmlRows = xmlDoc.SelectNodes("//group");
            //foreach (XmlNode xmlRow in xmlRows)
            foreach (TaskMilestone taskMilestone in taskMilestones)
            {

                // empty row to match group name
                writer.AddAttribute("class", "GridHeader");
                writer.RenderBeginTag("tr");
                writer.AddAttribute("colspan", (quarter.Days).ToString());
                writer.AddAttribute("width", ((quarter.Days) * int.Parse(_CellWidth)).ToString());
                writer.RenderBeginTag("th");
                //writer.Write("&nbsp;<img src='" + BlankGifPath + "' height='" + _CellHeight + "' width=" + ((quarter.Days) * int.Parse(_CellWidth)) + "/>&nbsp;");
                writer.RenderEndTag();
                writer.RenderEndTag();

                blockcolor = "#3366CC";

                //XmlNode node = xmlRow.SelectSingleNode("blockcolor");
                //if (node != null)
                //{
                //    blockcolor = node.InnerText;
                //}
                //else
                //{
                //    blockcolor = BlockColor;
                //}

                // write out the events
                //string strHTML;
                //XmlNodeList xmlBlocks = xmlRow.SelectNodes("block");
                //foreach (XmlNode xmlBlock in xmlBlocks)
                foreach (ProjectTask projectTask in projectTasks)
                {
                    if (projectTask.TaskMilestoneID == taskMilestone.TaskMilestoneID)
                    {
                        ProjectTask pt = projectTask;
                        Task task = tasks.FirstOrDefault(x => x.TaskID == pt.TaskID);
                        if (task != null)
                        {
                            writer.RenderBeginTag("tr");
                            startdate = task.StartDate.ToShortDateString(); //xmlBlock.SelectSingleNode("StartDate").InnerText;
                            enddate = task.DueDate.ToShortDateString(); //xmlBlock.SelectSingleNode("EndDate").InnerText;
                            href = "#"; // xmlBlock.SelectSingleNode("href").InnerText;
                            blocktext = task.Subject; // xmlBlock.SelectSingleNode("name").InnerText;

                            startindex = quarter.getColumnIndex(startdate);
                            endindex = quarter.getColumnIndex(enddate);

                            //write out the padding cells
                            for (int i = 0; i < startindex; i++)
                            {
                                //writer.AddAttribute("width", _CellWidth);
                                //writer.AddAttribute("height", _CellHeight);
                                writer.RenderBeginTag("td");
                                writer.Write("");
                                writer.RenderEndTag();
                            }
                            ;

                            //create the filled in block
                            writer.AddAttribute("colspan", (endindex - startindex + 1).ToString());
                            writer.AddAttribute("bgColor", blockcolor);
                            //writer.AddAttribute("width", _CellWidth);
                            //writer.AddAttribute("height", _CellHeight);
                            writer.AddAttribute("data-tooltip", "sticky" + task.TaskID);
                            writer.RenderBeginTag("td nowrap");
                            if (href != string.Empty)
                            {

                                //imagewidth = (endindex - startindex + 1)*int.Parse(_CellWidth);

                                //strHTML =
                                //    @"<img src='" + BlankGifPath + "' border='0' width='" +
                                //    imagewidth +
                                //    @"' height='" + 1 +
                                //    @"' alt='" + blocktext +
                                //    @"'/>";

                                //writer.Write("");
                                ////writer.Write(strHTML);
                            }
                            else
                            {
                                writer.Write("");
                            }
                            writer.RenderEndTag();
                            //

                            //write out the padding cells
                            for (int i = endindex; i < quarter.Days - 1; i++)
                            {
                                //writer.AddAttribute("width", _CellWidth);
                                //writer.AddAttribute("height", _CellHeight);
                                writer.RenderBeginTag("td");
                                writer.Write("&nbsp;");
                                writer.RenderEndTag();
                            }
                            writer.RenderEndTag();
                        }
                    }
                }
            }
            writer.RenderEndTag(); // close table tag
            writer.RenderEndTag(); // close div tag
        }
        #endregion

        #region Helper Classes
        private class QuarterHelper
        {
            private int m_year;
            private int m_quarter;
            private string[] m_names = new string[3];
            private int m_NoOfDays;

            public QuarterHelper()
            { }

            public QuarterHelper(int year, int quarter)
            {
                m_quarter = quarter;
                m_year = year;
                m_names = getQuarterNames();
                m_NoOfDays = getDaysInQuarter(m_year, m_quarter);
            }

            public int Year
            {
                get
                {
                    return m_year;
                }
            }

            public int QuarterIndex
            {
                get
                {
                    return m_quarter;
                }
            }

            public string[] Names
            {
                get
                {
                    return m_names;
                }
            }

            public int Days
            {
                get
                {
                    return m_NoOfDays;
                }
            }

            public string GetMonthName(int i)
            {
                return m_names[i - 1];
            }

            public int TotalDays()
            {
                int retval = 0;
                switch (m_quarter)
                {
                    case 1:
                        retval = DateTime.DaysInMonth(m_year, 1);
                        retval += DateTime.DaysInMonth(m_year, 2);
                        retval += DateTime.DaysInMonth(m_year, 3);
                        break;
                    case 2:
                        retval = DateTime.DaysInMonth(m_year, 4);
                        retval += DateTime.DaysInMonth(m_year, 5);
                        retval += DateTime.DaysInMonth(m_year, 6);
                        break;
                    case 3:
                        retval = DateTime.DaysInMonth(m_year, 7);
                        retval += DateTime.DaysInMonth(m_year, 8);
                        retval += DateTime.DaysInMonth(m_year, 9);
                        break;
                    case 4:
                        retval = DateTime.DaysInMonth(m_year, 10);
                        retval += DateTime.DaysInMonth(m_year, 11);
                        retval += DateTime.DaysInMonth(m_year, 12);
                        break;
                }
                return retval;
            }

            public int TotalDaysInMonth(int i)
            {
                return DateTime.DaysInMonth(m_year, i);
            }

            public string GetDayName(int month, int day)
            {
                string retval = string.Empty;
                DateTime d = new DateTime(m_year, month, day);
                switch (d.DayOfWeek)
                {
                    case DayOfWeek.Monday: retval = "Mo"; break;
                    case DayOfWeek.Tuesday: retval = "Tu"; break;
                    case DayOfWeek.Wednesday: retval = "We"; break;
                    case DayOfWeek.Thursday: retval = "Th"; break;
                    case DayOfWeek.Friday: retval = "Fr"; break;
                    case DayOfWeek.Saturday: retval = "Sa"; break;
                    case DayOfWeek.Sunday: retval = "Su"; break;
                }
                return retval;
            }

            private string[] getQuarterNames()
            {
                string[] retval = new string[3];

                switch (m_quarter)
                {
                    case 1:
                        retval[0] = "January";
                        retval[1] = "Febuary";
                        retval[2] = "March";
                        break;
                    case 2:
                        retval[0] = "April";
                        retval[1] = "May";
                        retval[2] = "June";
                        break;
                    case 3:
                        retval[0] = "July";
                        retval[1] = "August";
                        retval[2] = "September";
                        break;
                    case 4:
                        retval[0] = "October";
                        retval[1] = "November";
                        retval[2] = "December";
                        break;
                }

                return retval;

            }

            private int getDaysInQuarter(int year, int quarter)
            {
                DateTime dtS, dtE;
                if (quarter < 4)
                {
                    dtS = new DateTime(year, (3 * quarter - 2), 1);
                    dtE = new DateTime(year, (3 * quarter - 2) + 3, 1);
                }
                else
                {
                    dtS = new DateTime(year, (3 * quarter - 2), 1);
                    dtE = new DateTime(year + 1, 1, 1);
                }

                TimeSpan ts = new TimeSpan(dtE.Subtract(dtS).Ticks);
                return ts.Days;
            }

            public int getColumnIndex(string day)
            {
                DateTime dt = DateTime.Parse(day);
                int offset = 0;
                int retval = 0;
                for (int i = 1; i < m_quarter; i++)
                {
                    offset += getDaysInQuarter(m_year, i);
                }
                retval = (dt.DayOfYear - 1) - offset;
                if (retval < 0) retval = 0;
                if (retval > getDaysInQuarter(m_year, m_quarter)) retval = getDaysInQuarter(m_year, m_quarter);
                return retval;
            }
        }
        #endregion

    }


}
